internal class ChannelTriangle:PapuChannel{
	
	
	PAPU papu;
	
	bool _isEnabled;
    internal bool sampleCondition;
	bool lengthCounterEnable;
	bool lcHalt;
	bool lcControl;

    internal int progTimerCount;
    internal int progTimerMax;
    internal int triangleCounter;
    internal int lengthCounter;
    internal int linearCounter;
	int lcLoadValue;
    internal int sampleValue;
	int tmp;
	
	
	internal ChannelTriangle(PAPU papu){
		this.papu = papu;
	}
	
	internal void clockLengthCounter(){
		if(lengthCounterEnable && lengthCounter>0){
			lengthCounter--;
			if(lengthCounter==0){
				updateSampleCondition();
			}
		}
	}
	
	internal void clockLinearCounter(){
		
		if(lcHalt){
			
			// Load:
			linearCounter = lcLoadValue;
			updateSampleCondition();
			
		}else if(linearCounter > 0){
			
			// Decrement:
			linearCounter--;
			updateSampleCondition();
			
		}
		
		if(!lcControl){
			
			// Clear halt flag:
			lcHalt = false;
			
		}
		
	}
	
	internal override int getLengthStatus(){
		return ((lengthCounter==0 || !_isEnabled)?0:1);
	}
	
	internal int readReg(int address){
		return 0;
	}
	
	internal override void writeReg(int address, int value){
		
		if(address == 0x4008){
			
			// New values for linear counter:
			lcControl 	= (value&0x80)!=0;
			lcLoadValue =  value&0x7F;
			
			// Length counter enable:
			lengthCounterEnable = !lcControl;
			
		}else if(address == 0x400A){
			
			// Programmable timer:
			progTimerMax &= 0x700;
			progTimerMax |= value;
			
		}else if(address == 0x400B){
			
			// Programmable timer, length counter
			progTimerMax &= 0xFF;
			progTimerMax |= ((value&0x07)<<8);
			lengthCounter = papu.getLengthMax(value&0xF8);
			lcHalt = true;
			
		}
		
		updateSampleCondition();
		
	}
	
	internal void clockProgrammableTimer(int nCycles){
		
		if(progTimerMax>0){
			progTimerCount+=nCycles;
			while(progTimerMax>0 && progTimerCount>=progTimerMax){
				progTimerCount-=progTimerMax;
				if(_isEnabled && lengthCounter>0 && linearCounter>0){
					clockTriangleGenerator();
				}
			}
		}
		
	}
	
	internal void clockTriangleGenerator(){
		triangleCounter++;
		triangleCounter &= 0x1F;
	}
	
	internal override void setEnabled(bool value){
		_isEnabled = value;
		if(!value)lengthCounter = 0;
		updateSampleCondition();
	}
	
	internal override bool isEnabled(){
		return _isEnabled;
	}

	internal void updateSampleCondition(){
		sampleCondition = 
			_isEnabled 		&& 
			progTimerMax>7 	&&
			linearCounter>0 && 
			lengthCounter>0
		;
	}

	internal override void reset(){
		
		progTimerCount = 0;
		progTimerMax = 0;
		triangleCounter = 0;
		_isEnabled = false;
		sampleCondition = false;
		lengthCounter = 0;
		lengthCounterEnable = false;
		linearCounter = 0;
		lcLoadValue = 0;
		lcHalt = true;
		lcControl = false;
		tmp = 0;
		sampleValue = 0xF;
		
	}
	
	internal void destroy(){
		papu = null;
	}
	
}